package com.sgzn.sgpay.aop;

import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.exception.SgpayException;
import com.sgzn.sgpay.exception.ValidateException;
import com.sgzn.sgpay.model.request.SgsDeviceQueryRequest;
import com.sgzn.sgpay.model.request.able.SgsReqAble;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.service.support.SgsResponseUtil;
import com.sgzn.sgpay.util.ValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 接口服务类AOP
 * @author zhongzhongyong
 * @version Id: ServiceAop.java, v 0.1 2018/4/3 15:21 zhongzhongyong Exp $$
 */
@Aspect
@Service
@Slf4j
public class ServiceAop {

    @Resource
    private ValidateUtil validateUtil;

    @Pointcut(value = "execution(public com.sgzn.sgpay.model.response.SgsResultResponse com.sgzn.sgpay.service.impl..*.*(..)) && args(request,..)")
    private void servicePointcut(SgsReqAble request) {
        //do nothing here
    }

    @Around("servicePointcut(request)")
    public SgsResultResponse aroundMethod(ProceedingJoinPoint jp, SgsReqAble request) throws Throwable {
        long startMillis = System.currentTimeMillis();


        String className = jp.getTarget().getClass().getSimpleName();
        String methodName = jp.getSignature().getName();
        Object[] args = jp.getArgs();

        //获取initiationID
        String initiationID = request.getInitiationID();

        SgsResultResponse response;
        String succFlag = "Success";
        try {
            MDC.put("initiationID", initiationID);
            // 1. 校验
            for(int i=0, length = args.length; i<length; i++){
                if (args[i] == null){
                    throw new IllegalArgumentException("Request must be not null");
                } else {
                    validateUtil.validate(args[i]);
                }
            }
            if(!(request instanceof SgsDeviceQueryRequest)){
                log.info("call[{}][{}]PARAMETER:[{}]", className, methodName, request);
            }

            response = (SgsResultResponse) jp.proceed();
        }catch (ValidateException e) {
            succFlag = "Failure";
            log.error("Here throw an ValidateException:", e);
            response = SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C10001.getResponseCode(), e.getMessage());
        }catch (SgpayException e) {
            succFlag = "Failure";
            log.error("Here throw an SgpayException:{}", e.getMessage());
            response = SgsResponseUtil.INSTANCE.fail(e.getCode(), e.getDesc());
        }catch (Exception e) {
            succFlag = "Failure";
            log.error("Here throw an Exception:", e);
            response = SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C503.getResponseCode(),SgsResponseCode.C503.getResponseDesc());
        }
        if(!(request instanceof SgsDeviceQueryRequest)){
            log.info("call[{}][{}][{}ms][{}][{}]RESPONSE:Result[{}]", className, methodName, System.currentTimeMillis() - startMillis, succFlag, response.getErrorCode(), response);
        }
        return response;
    }
}
